package com.dk.aspect;

import com.dk.annotation.DataSource;
import com.dk.config.DynamicDataSource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @ClassName DataSourceAspect
 * @Description 数据源的切面类  用于扫描mapper包下所有方法上的注解 然后选择对应的数据源
 * @Author Eayon
 * @Date 2020/6/3 19:18
 * @Version 1.0
 */
@Aspect
@Component
public class DataSourceAspect {

    private static final Logger log = LoggerFactory.getLogger(DataSourceAspect.class);

    /**
     * 配置切点：方法上带有我们自定义这个注解的就切
     * 被切到就会执行下面的环绕通知去切换数据源
     */
    @Pointcut("@annotation(com.dk.annotation.DataSource)")
    public void PointCut() {

    }

    /**
     * 环绕通知：将被切到的方法进行切换数据源
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("PointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        try {
            // 获取当前被切到的方法
            MethodSignature signature = (MethodSignature) point.getSignature();
            //获取被切到的方法
            Method method = signature.getMethod();
            //获取方法上我们自定义的DataSource注解
            DataSource dataSource = method.getAnnotation(DataSource.class);
            //判断该方法有没有该注解
            if (dataSource == null) {
                // 如果没有注解，那就默认使用master数据源
                DynamicDataSource.setDataSource("ds-master");
                log.info("使用默认master数据源");
            } else {
                // 如果有注解，就是用该注解name属性的值是哪个数据源就切换成哪个数据源
                DynamicDataSource.setDataSource(dataSource.name());
                log.info("使用注解定义数据源：{}",dataSource.name());
            }
            // 执行目标方法
            return point.proceed();
        } finally {
            DynamicDataSource.clearDataSource();
        }
    }
}
